home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / scale / scale1.asm < prev    next >
Encoding:
Assembly Source File  |  1993-04-29  |  10.9 KB  |  222 lines

  1. ;=========================================================================
  2. ; SCALE1.ASM By John A. Slagel, jas37876@uxa.cso.uiuc.edu.
  3. ; This is some code to do bitmap scaling on an 256 color bitmap.  This can
  4. ; be used to write to VGA memory or a virtual page in system memory by
  5. ; simply changing the ScreenPtr and BytesPerLine variables. It can scale a
  6. ; bitmap of any size down to 2 pixels wide, or up to thousands of pixels
  7. ; wide.  It performs complete clipping, with only a small constant amount
  8. ; of time to clip, no matter how huge the image is.  The inner scanline
  9. ; loop has been optimized for no memory accesses, except to read or
  10. ; write a pixel.  This uses MASM 5.1 features, and can be compiled in any
  11. ; memory model by changing the .MODEL line, but make sure that you always
  12. ; pass a far pointer to the bitmap data, regardless of memory model.
  13. ; C-callable as:
  14. ;   void SCALE1( int X, int Y, int DW, int DY,
  15. ;                     int SW, int SH, void far * Bitmap );
  16. ; X,Y   are the upper left-hand coordinates of where to draw the bitmap.
  17. ; DW,DH are the width and height of the SCALEed bitmap
  18. ; SW,SH are the width and height of the source bitmap.
  19. ; Bitmap is a pointer to the bitmap bits.
  20. ;
  21. ;==========================================================================
  22. .MODEL LARGE, C
  23. .386
  24.  
  25. .DATA
  26. ; Make these externs if you want your program to change them.
  27. ClipLt          DW  20                  ; Left clipping boundry
  28. ClipRt          DW  300                 ; Right clipping boundry
  29. ClipTp          DW  20                  ; Top clipping boundry
  30. ClipBt          DW  190                 ; Bottom clipping boundry
  31. ScreenPtr       DD  0A0000000h          ; Where to draw in memory.
  32. BytesPerLine    DW  320                 ; Bytes per scanline
  33.  
  34. .CODE
  35.  
  36. SCALE1  PROC FAR USES DS DI SI, DestX:WORD, DestY:WORD, DestWidth:WORD, DestHeight:WORD, SourceWidth:WORD, SourceHeight:WORD, Bitmap:FAR PTR
  37. LOCAL   DecisionX:WORD, DecisionY:WORD, ClippedWidth:WORD, ClippedHeight:WORD, SourceWidth2:WORD
  38.  
  39.         mov     ax, @DATA
  40.         mov     ds, ax
  41.  
  42.         cmp     DestWidth, 2        ; If destination width is less than 2
  43.         jl      Done                ;     then don't draw it.
  44.  
  45.         cmp     DestHeight, 2       ; If destination height is less than 2
  46.         jl      Done                ;     then don't draw it.
  47.  
  48.         mov     ax, DestY           ; If it is completely below the
  49.         cmp     ax, ClipBt          ; lower clip bondry,
  50.         jg      Done                ;     then don't draw it.
  51.  
  52.         add     ax, DestHeight      ; If it is above clip boundries
  53.         dec     ax                  ;     then don't draw it.
  54.         cmp     ax, ClipTp
  55.         jl      Done
  56.  
  57.         mov     ax, DestX           ; If it is to the right of the
  58.         mov     cx, ClipRt          ; right clip boundry
  59.         cmp     ax, ClipRt          ;     then don't draw it.
  60.         jg      Done
  61.  
  62.         add     ax, DestWidth       ; If it is completely to the left
  63.         dec     ax                  ; of the left clip boundry,
  64.         cmp     ax, ClipLt          ;     then don't draw it.
  65.         jl      Done
  66.  
  67.         lfs     si, Bitmap          ; Make FS:SI point to bitmap data
  68.  
  69.         mov     ax, DestWidth       ; ClippedWidth is initially set to
  70.         mov     ClippedWidth, ax    ; the requested dest width.
  71.  
  72.         shl     ax,1                ; Initialize the X decision var
  73.         neg     ax                  ; to be -2*DestWidth
  74.         mov     DecisionX, ax       ;
  75.  
  76.         mov     ax, DestHeight      ; ClippedHeight is initially set to
  77.         mov     ClippedHeight, ax   ; the requested dest size.
  78.  
  79.         shl     ax,1                ; Initialize the Y decision var
  80.         neg     ax                  ; to be -2*DestHeight
  81.         mov     DecisionY, ax       ;
  82.  
  83.         movsx   eax, ClipTp         ; If Y is below the top
  84.         mov     edx, eax            ; clipping boundry, then we don't
  85.         sub     dx, DestY           ; need to clip the top, so we can
  86.         js      NoTopClip           ; jump over the clipping stuff.
  87.  
  88.         mov     DestY, ax           ; This block performs clipping on the
  89.         sub     ClippedHeight, dx   ; top of the bitmap.  I have heavily
  90.         movsx   ecx, SourceHeight   ; optimized this block to use only 4
  91.         imul    ecx, edx            ; 32-bit registers, so I'm not even
  92.         mov     eax, ecx            ; gonna try to explain what it's doing.
  93.         mov     edx, 0              ; But I can tell you what results from
  94.         movsx   ebx, DestHeight     ; this:  The DecisionY var is updated
  95.         idiv    ebx                 ; to start at the right clipped row.
  96.         movsx   edx, SourceWidth    ; Y is moved to the top clip
  97.         imul    edx, eax            ; boundry. ClippedHeight is lowered since
  98.         add     si, dx              ; we won't be drawing all the requested
  99.         imul    eax, ebx            ; rows.  SI is changed to point over
  100.         sub     ecx, eax            ; the bitmap data that is clipped off.
  101.         sub     ecx, ebx            ;
  102.         shl     ecx, 1              ;
  103.         mov     DecisionY, cx       ; <end of top clipping block >
  104.  
  105. NoTopClip:
  106.         mov     ax, DestY           ; If the bitmap doesn't extend over the
  107.         add     ax, ClippedHeight   ; bottom clipping boundry, then we
  108.         dec     ax                  ; don't need to clip the bottom, so we
  109.         cmp     ax, ClipBt          ; can jump over the bottom clip code.
  110.         jle     NoBottomClip        ;
  111.  
  112.         mov     ax, ClipBt          ; Clip off the bottom by reducing the
  113.         sub     ax, DestY           ; ClippedHeight so that the bitmap won't
  114.         inc     ax                  ; extend over the lower clipping
  115.         mov     ClippedHeight, ax   ; boundry.
  116.  
  117. NoBottomClip:
  118.         movsx   eax, ClipLt         ; If X is to the left of the
  119.         mov     edx, eax            ; top clipping boundry, then we don't
  120.         sub     dx, DestX           ; need to clip the left, so we can
  121.         js      NoLeftClip          ; jump over the clipping stuff.
  122.  
  123.         mov     DestX, ax           ; This block performs clipping on the
  124.         sub     ClippedWidth, dx    ; left of the bitmap.  I have heavily
  125.         movsx   ecx, SourceWidth    ; optimized this block to use only 4
  126.         imul    ecx, edx            ; 32-bit registers, so I'm not even
  127.         mov     eax, ecx            ; gonna try to explain what it's doing.
  128.         mov     edx, 0              ; But I can tell you what results from
  129.         movsx   ebx, DestWidth      ; this:  The DecisionX var is updated
  130.         idiv    ebx                 ; to start at the right clipped column.
  131.         add     si, ax              ; X is moved to the left clip
  132.         imul    eax, ebx            ; boundry. ClippedWidth is reduced since
  133.         sub     ecx, eax            ; we won't be drawing all the requested
  134.         sub     ecx, ebx            ; cols.  SI is changed to point over
  135.         shl     ecx, 1              ; the bitmap data that is clipped off.
  136.         mov     DecisionX, cx       ; <end of left clipping block >
  137.  
  138. NoLeftClip:
  139.         mov     ax, DestX           ; If the bitmap doesn't extend over the
  140.         add     ax, ClippedWidth    ; right clipping boundry, then we
  141.         dec     ax                  ; don't need to clip the right, so we
  142.         cmp     ax, ClipRt          ; can jump over the right clip code.
  143.         jle     NoClipRight         ;
  144.  
  145.         mov     ax, ClipRt          ; Clip off the right by reducing the
  146.         sub     ax, DestX           ; ClippedWidth so that the bitmap won't
  147.         inc     ax                  ; extend over the right clipping
  148.         mov     ClippedWidth, ax    ; boundry.
  149.  
  150.         ;Calculate starting video address
  151. NoClipRight:
  152.         les     di, ScreenPtr       ; Make ES:DI point to the dest memory.
  153.         mov     ax, DestY           ; Calculated as:
  154.         imul    ax, BytesPerLine ;
  155.         add     di, ax              ; DI=DI+Y*BytesPerScanLine+X
  156.         add     di, DestX           ; ES:DI -> Video memory
  157.  
  158.         ; Multiply all the widths, etc by 2 to reduce inner loop calcs.
  159.         shl     DestWidth,1         ; Dest width *= 2
  160.         shl     SourceHeight,1      ; SourceHeight *= 2
  161.         shl     DestHeight,1        ; DestHeight *= 2
  162.         mov     ax, SourceWidth
  163.         shl     ax, 1
  164.         mov     SourceWidth2, ax    ; Source Width *= 2
  165.  
  166.         ALIGN   4                   ; Since this point gets jumped to a lot,
  167.                                     ; make sure that it is DWORD aligned.
  168. RowLoop:
  169.         push    si                  ; Save the starting source index
  170.         push    di                  ; Save the starting dest index
  171.         push    bp                  ; Save the current base pointer
  172.  
  173.         mov     bx, DecisionX       ; Use BX for X decision variable
  174.         mov     cx, ClippedWidth    ; Use CX for column counter
  175.         mov     dx, SourceWidth2    ; Use DX for source width * 2
  176.         mov     bp, DestWidth       ; Use GS for dest width * 2
  177.         mov     al, fs:[si]         ; Get the first source pixel
  178.  
  179.         ; From this point to DoneWithScanLine is the critical inner-loop.
  180.         ALIGN   4                   ; Common jump point... align for speed.
  181. ScanLineLoop:
  182.         stosb                       ; Draw a pixel
  183.         dec     cx                  ; Decrement width counter
  184.         jz      DoneWithScanLine    ; See if we're done with this scan line
  185.         add     bx, dx              ; Increment the decision variable
  186.         js      ScanLineLoop        ; Do we increment the source pixel?
  187.  
  188. IncSourceCol:
  189.         inc     si                  ; Go on to next source pixel
  190.         sub     bx, bp              ; Decrement the decision variable
  191.         jns     IncSourceCol        ; See if we need to skip another source pixel
  192.         mov     al, fs:[si]         ; Get the next source pixel
  193.         jmp     ScanLineLoop        ; Start drawing this pixel
  194.  
  195. DoneWithScanLine:
  196.         pop     bp                  ; Restore BP to access variables
  197.         pop     di                  ; Restore DI to top row of screen
  198.         pop     si                  ; Restore SI to top row of source bits
  199.  
  200.         add     di, BytesPerLine
  201.         mov     bx, DecisionY       ; Use BX for the Y decision variable
  202.         add     bx, SourceHeight    ; Increment the Y decision variable
  203.         js      NextRow             ; Jump if we're in the same source row.
  204.  
  205. IncSourceRow:
  206.         add     si, SourceWidth     ; Move to next source row
  207.         sub     bx, DestHeight      ; Decrement Y decision variable
  208.         jns     IncSourceRow        ; See if we skip another source row
  209.  
  210. NextRow:
  211.         mov     DecisionY, bx       ; Free up BX for RowLoop
  212.         dec     ClippedHeight       ; If we're not at last row
  213.         jnz     RowLoop             ;    then do another row
  214. Done:
  215.         ret                         ; We're done!
  216.  
  217. SCALE1  ENDP
  218.  
  219.         END
  220.  
  221.  
  222.